﻿
// ## 2023/05/11 # 江东新风 # 仅在执政官功能开启时显示和执行 ##
// ## 2022/08/14 # 铃 # 从风神自动化内政中拿出自动运输,重新修改匹配新的内政 ##

namespace 自动运输
{

	const float 输送兵力比率 = 0.5f;

	// true =从后方城市到边境城市的运输（边界城市=距敌方城市2的距离）
	// false =从后方，边界城市到边界，前线城市的运输（前线城市=敌方城市和距离1）
	const bool 限制警戒城市运输 = false;

	// 수송부대가 출진할 도시의 최대 병력 대비 현재 병력의 비율
	// 기본값 설명 : 현재 병력이 최대 병력의 0.5배 이상인 경우 수송
	const float 可运输条件_兵力比例 = 0.5f;

	// 수송부대가 출진할 도시의 현재 병력 대비 현재 병량의 비율
	// 기본값 설명 : 현재 병량이 현재 병력의 1.5배 이상인 경우 수송
	const float 可运输条件_兵粮比例 = 1.5f;

	// 目标城市中当前兵力与最大兵力的比例
	// 默认说明：如果目标城市中的当前兵力少于最大兵力的0.5倍，则进行运输
	const float 可运输条件_兵力条件1 = 0.5f;

	// 运输出发城市中的兵力与目标城市的兵力的比例
	// 默认说明：当运输出发城市的当前兵力少于目标城市中当前部队人数的0.5倍时的运输。
	const float 可运输条件_兵力条件2 = 0.5f;

	/// =========================================================================================

	const bool 调试模式 = false;

	const int KEY = pk::hash("自动运输");


	class Main
	{

		///	<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

		Main()
		{
			/// 내정 자동화 설정 메뉴 配置自动运输的菜单
			add_menu_自动运输();

			/// 내정 자동화 실행 트리거 自动运输的执行程序
			pk::bind(112, pk::trigger112_t(回合结束_触发运输));

			/// 정보 관리용 트리거 情报管理触发器
		}

		///	<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
		// 增加对应菜单
		void add_menu_自动运输()
		{
			pk::menu_item 自动运输_上位菜单_许可;
			自动运输_上位菜单_许可.menu = auto_IA_menu::菜单_自动内政;
			;
			自动运输_上位菜单_许可.shortcut = "X";
			自动运输_上位菜单_许可.init = pk::building_menu_item_init_t(init);
			自动运输_上位菜单_许可.get_image_id = pk::menu_item_get_image_id_t(getImageID_1249);
			自动运输_上位菜单_许可.is_visible = pk::menu_item_is_visible_t(isVisible);
			自动运输_上位菜单_许可.get_text = cast<pk::menu_item_get_text_t @>(function() { return pk::encode("自动运输开关"); });
			自动运输_上位菜单_许可.get_desc = cast<pk::menu_item_get_desc_t @>(function() { return pk::encode("点击展开或收起"); });
			自动运输_上位菜单_许可.handler = pk::menu_item_handler_t(handler_上位菜单_许可);
			pk::add_menu_item(自动运输_上位菜单_许可);

			pk::menu_item 自动运输_菜单_运输_许可;
			自动运输_菜单_运输_许可.menu = auto_IA_menu::菜单_自动内政;
			;
			自动运输_菜单_运输_许可.is_visible = pk::menu_item_is_visible_t(isMenuVisible_许可);
			自动运输_菜单_运输_许可.shortcut = "T";
			自动运输_菜单_运输_许可.get_text = pk::menu_item_get_text_t(getText_运输);
			自动运输_菜单_运输_许可.get_desc = pk::menu_item_get_desc_t(getDesc_运输);
			自动运输_菜单_运输_许可.handler = pk::menu_item_handler_t(handler_运输);
			pk::add_menu_item(自动运输_菜单_运输_许可);
		}

		//	*************************************菜单相关***********************************************************

		int menu_city_id_;
		int menu_force_id_;
		pk::building @building_;

		void init(pk::building @building)
		{
			@building_ = @building;
			pk::city @city = pk::building_to_city(building);

			menu_city_id_ = (city !is null) ? city.get_id() : -1;
			menu_force_id_ = building.get_force_id();
		}

		int getImageID_1249() // 주황색
		{
			return 1249;
		}

		bool isVisible()
		{
			if (!ch::get_auto_affairs_status())return false;
			if (building_.get_id() >= 城市_末)
				return false;
			if (!pk::is_player_controlled(pk::get_city(menu_city_id_)))
				return false;

			return menu_city_id_ != -1 and menu_force_id_ == pk::get_current_turn_force_id();
		}

		string getText_运输()
		{
			return isEnabled(menu_force_id_, menu_city_id_) ? pk::encode("禁止运输") : pk::encode("允许运输");
		}
		string getDesc_运输()
		{
			return isEnabled(menu_force_id_, menu_city_id_) ? pk::encode("是否禁止城市运输.") : pk::encode("是否允许城市运输.");
		}
		bool handler_运输()
		{
			
			toggle(menu_force_id_, menu_city_id_);
			return true;
		}

		bool handler_上位菜单_许可()
		{
			auto_IA_menu::自动化_展开_当前 = (auto_IA_menu::自动化_展开_当前 == auto_IA_menu::自动化_展开_运输) ? 0 : auto_IA_menu::自动化_展开_运输;
			return false;
		}

		bool isMenuVisible_许可()
		{
			if (auto_IA_menu::自动化_展开_当前 != auto_IA_menu::自动化_展开_运输)
				return false;
			return true;
		}

		void 回合结束_触发运输(pk::force @force)
		{
			if (!ch::get_auto_affairs_status())return;
			if (!force.is_player())
				return; // 计算机势力除外 컴퓨터 세력 제외

			array<pk::city @> city_list = pk::list_to_array(pk::get_city_list(force)); // 세력 도시 清单
			for (int i = 0; i < int(city_list.length); i++)
			{
				pk::city @city = city_list[i];
				pk::building @building = pk::city_to_building(city);

				// if (调试模式)
				// {
				// 	string city_name = pk::format("城市\x1b[1x{}\x1b[0x", pk::decode(pk::get_name(city)));
				// 	pk::message_box(pk::encode(pk::format("已确认{}", city_name)));
				// }

				if (!pk::is_player_controlled(building))
					continue; // 플레이어 위임군단 도시인 경우 제외
				if (pk::get_idle_person_list(building).count == 0)
					continue; // 행동가능 무장이 없는 경우 제외
				/// 참고 사항
				// cmd 구조체를 사용하여 내정 명령을 실행하는 경우 실행이 불가능한 상황이면 알아서 실행하지 않음 (무장 포상 제외)
				// 따로 실행이 불가능한 경우를 조건으로 추가하지 않아도 됨 (행동력 소비량, 요구 시설, 행동가능 무장 존재, 금 소비량 등)
				auto base_t = ch::get_base_p(city.get_id());
				func_自动运输_运输(force, city);
			}
		}

		void func_自动运输_运输(pk::force @force, pk::city @city)
		{
			pk::building @building = pk::city_to_building(city);
			pk::district @district = pk::get_district(building.get_district_id());
			auto base_t = ch::get_base_p(city.get_id());


			if (pk::get_idle_person_list(building).count == 0)
				return; // 행동가능 무장 조건

			// 설정 조건 확인

			if (!base_t.can_transport)
				return; // 허용/금지 여부


			// 수송 한계 도시 조건 (수송하는 도시)
			if (限制警戒城市运输)
			{
				if (func_附近_敌城市数(city, 2) > 0)
					return;
			}
			else
			{
				if (func_附近_敌城市数(city, 1) > 0)
					return;
			}

		
			for (int i = 0; i < 6; i++)
			{
				pk::city @neighbor_city = pk::get_city(city.neighbor[i]);
				if (neighbor_city is null)
					continue; // 비어 있는 인접 도시 번호인 경우 제외
				if (!pk::is_alive(neighbor_city))
					continue;
				if (neighbor_city.get_force_id() != force.get_id())
					continue; // 인접 도시가 해당 세력이 아닌 경우 제외

				pk::building @neighbor_building = pk::city_to_building(neighbor_city);

				if (pk::get_idle_person_list(building).count == 0)
					return; // 행동가능 무장 조건

				if (调试模式)
				{
					string city_name = pk::format("城市\x1b[1x{}\x1b[0x", pk::decode(pk::get_name(city)));
					pk::message_box(pk::encode(pk::format("兵力一次判断 {},{},{}", city_name,city.troops,city.max_troops * 可运输条件_兵力比例)));
				}


				// 병력 조건 (수송하는 도시)
				if (city.troops < int(city.max_troops * 可运输条件_兵力比例))
					return;

				if (调试模式)
				{
					string city_name = pk::format("城市\x1b[1x{}\x1b[0x", pk::decode(pk::get_name(city)));
					pk::message_box(pk::encode(pk::format("兵粮二次判断 {},{},{},{}", city_name,city.food,int(city.troops * 可运输条件_兵粮比例),(city.food < int(city.troops * 可运输条件_兵粮比例)))));
				}

				// 병량 조건 (수송하는 도시)
				if (city.food < int(city.troops * 可运输条件_兵粮比例))
					return;

				if (调试模式)
				{
					string city_name = pk::format("城市\x1b[1x{}\x1b[0x", pk::decode(pk::get_name(city)));
				pk::message_box(pk::encode(pk::format("兵粮三次判断 {},{},{},{}", city_name,city.food,int(city.troops * 可运输条件_兵粮比例),(city.food < int(city.troops * 可运输条件_兵粮比例)))));
				}



				// 수송 한계 도시 조건 (수송받는 도시)
				if (限制警戒城市运输)
				{
					if (func_附近_敌城市数(neighbor_city, 1) > 0)
						continue;
				}

				// 플레이어 위임군단 도시 제외 (수송받는 도시)
				if (neighbor_building.is_player() and !pk::is_player_controlled(neighbor_building))
					continue;

				// 병력 조건 (수송받는 도시)
				if (neighbor_city.troops > int(neighbor_city.max_troops * 可运输条件_兵力条件1))
					continue;

				// 병력 조건 (수송하는 도시 vs 수송받는 도시)
				if (neighbor_city.troops > int(city.troops * 可运输条件_兵力条件2))
					continue;

				// 근처 적 도시수 조건  (수송하는 도시 vs 수송받는 도시)
				if (!func_附近_敌城市数_条件_是否满足(city, neighbor_city))
					continue;

				func_运输部队出征(building, neighbor_building);
			}
		}

		void func_运输部队出征(pk::building @building, pk::building @neighbor_building)
		{
			/// 출진 명령 정보
			pk::com_deploy_cmd_info cmd;

			// 출진 거점
			@cmd.base = @building;

			// 출진 부대 종류
			cmd.type = 部队类型_运输;

			// 출진 부대 주장
			pk::list<pk::person @> person_list = pk::get_idle_person_list(building);
			person_list.sort(function(a, b) { return a.stat[武将能力_政治] > b.stat[武将能力_政治]; });
			cmd.member[0] = person_list[0].get_id();

			// 출진 부대 금
			int 金运输量_最大值 = pk::min(pk::get_gold(building), pk::get_max_gold(neighbor_building) - pk::get_gold(neighbor_building));
			cmd.gold = (pk::get_gold(building) >= 10000) ? pk::min(金运输量_最大值, (pk::get_gold(building) / 2)) : (pk::get_gold(building) / 4);

			// 출진 부대 병력
			int 兵运输量_最大值 = pk::min(pk::get_troops(building), pk::get_max_troops(neighbor_building) - pk::get_troops(neighbor_building));
			兵运输量_最大值 = pk::min(60000, 兵运输量_最大值);
			int 兵运输量 = pk::min(兵运输量_最大值, int(pk::get_troops(building) * 输送兵力比率));
			cmd.troops = 兵运输量;

			// 출진 부대 병량
			float 兵系数 = (pk::get_food(building) >= int(pk::get_troops(building) * 2.0f)) ? 3.0f : 1.5f;
			int 军粮运输量_最大值 = pk::min(pk::get_food(building), pk::get_max_food(neighbor_building) - pk::get_food(neighbor_building));
			cmd.food = (pk::get_food(building) >= 100000) ? pk::max((pk::get_food(building) / 2), pk::min(军粮运输量_最大值, int(兵运输量 * 兵系数))) : (pk::get_food(building) / 2);

			// 출진 부대 병기(수송량)
			// 참고 : 0검, 1창, 2극, 3노, 4군마, 5충차, 6정란, 7투석, 8목수, 9주가, 10누선, 11투함
			array<int> 수송량_병기(12, 0);
			for (int i = 0; i < 兵器_末; i++)
			{
				int 수송량_병기_최대치 = pk::get_max_weapon_amount(neighbor_building, i) - pk::get_weapon_amount(neighbor_building, i);
				수송량_병기[i] = pk::min(수송량_병기_최대치, pk::get_weapon_amount(building, i) / 2);
				cmd.weapon_id[i] = i;
				cmd.weapon_amount[i] = 수송량_병기[i];
			}

			// 출진 부대 임무
			cmd.order = 部队任务_移动;

			// 출진 부대 목표 좌표
			cmd.target_pos = neighbor_building.pos;

			// 출진 명령 실행
			int unit_id = pk::command(cmd);

			// 출진 실행 메시지
			if (unit_id != -1)
			{
				pk::unit @unit = pk::get_unit(unit_id);
				string unit_name = pk::format("\x1b[1x{}\x1b[0x", pk::decode(pk::get_name(unit)));
				string building_name = pk::format("\x1b[1x{}\x1b[0x", pk::decode(pk::get_name(building)));
				string neighbor_building_name = pk::format("\x1b[1x{}\x1b[0x", pk::decode(pk::get_name(neighbor_building)));
				string action_message = pk::format("{}从{}运输到{}", unit_name, building_name, neighbor_building_name);
				pk::force @force = pk::get_force(building.get_force_id());

				pk::message_box(pk::encode(action_message));

				// 출진 부대 행동 완료
				unit.action_done = true;
			}
		}

		bool func_附近_敌城市数_条件_是否满足(pk::city @city, pk::city @neighbor_city)
		{
			if (func_附近_敌城市数(city, 1) < func_附近_敌城市数(neighbor_city, 1))
				return true;
			else if (func_附近_敌城市数(city, 1) > func_附近_敌城市数(neighbor_city, 1))
				return false;
			else
			{
				if (func_附近_敌城市数(city, 2) < func_附近_敌城市数(neighbor_city, 2))
					return true;
				else if (func_附近_敌城市数(city, 2) > func_附近_敌城市数(neighbor_city, 2))
					return false;
				else
				{
					if (func_附近_敌城市数(city, 3) < func_附近_敌城市数(neighbor_city, 3))
						return true;
					else if (func_附近_敌城市数(city, 3) > func_附近_敌城市数(neighbor_city, 3))
						return false;
					else
					{
						if (func_附近_敌城市数(city, 4) < func_附近_敌城市数(neighbor_city, 4))
							return true;
						else if (func_附近_敌城市数(city, 4) > func_附近_敌城市数(neighbor_city, 4))
							return false;
						else
						{
							if (func_附近_敌城市数(city, 5) < func_附近_敌城市数(neighbor_city, 5))
								return true;
							else if (func_附近_敌城市数(city, 5) > func_附近_敌城市数(neighbor_city, 5))
								return false;
							else
							{
								if (func_附近_敌城市数(city, 6) < func_附近_敌城市数(neighbor_city, 6))
									return true;
								else if (func_附近_敌城市数(city, 6) > func_附近_敌城市数(neighbor_city, 6))
									return false;
								else
								{
									if (func_附近_敌城市数(city, 7) < func_附近_敌城市数(neighbor_city, 7))
										return true;
									else if (func_附近_敌城市数(city, 7) > func_附近_敌城市数(neighbor_city, 7))
										return false;
									else
									{
										if (func_附近_敌城市数(city, 8) < func_附近_敌城市数(neighbor_city, 8))
											return true;
										else
											return false;
									}
								}
							}
						}
					}
				}
			}
		}

		int func_附近_敌城市数(pk::city @city, int 도시거리)
		{
			int enemy_city_count = 0;

			array<pk::city @> cities = pk::list_to_array(pk::get_city_list());
			for (int i = 0; i < int(cities.length); i++)
			{
				pk::city @neighbor_city = cities[i];

				// 도시 간 무장의 이동 소요일수 기준
				int distance = pk::get_city_distance(city.get_id(), neighbor_city.get_id());

				if (distance > 도시거리)
					continue;
				if (!pk::is_enemy(city, neighbor_city))
					continue;

				enemy_city_count++;
			}

			return enemy_city_count;
		}

		string numberpad_t(int line, int original_value, int current_value)
		{
			return pk::encode("");
		}

		bool isEnabled(int force_id, int city_id)
		{
			auto base_t = ch::get_base_p(city_id);

			return base_t.can_transport;

		}

		void toggle(int force_id, int city_id)
		{
			bool 允许与否 = false;

			允许与否 = isEnabled(force_id, city_id);

			string str_允许与否 = (!允许与否) ? "\x1b[1x允许\x1b[0x" : "\x1b[1x禁止\x1b[0x";

			set(city_id, !允许与否);

			if (force_id == pk::get_current_turn_force_id())
			{
				string city_name = pk::decode(pk::get_name(pk::city_to_building(pk::get_city(city_id))));
				string toggle_msg = pk::format("将\x1b[1x{}\x1b[0x的自动运输改为:{}", city_name, str_允许与否);
				pk::message_box(pk::encode(toggle_msg));
			}
		}

		void set(int city_id, bool value)
		{
			auto base_t = ch::get_base_p(city_id);
			base_t.can_transport = value;
		}

	} Main main;
}